import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@WebServlet(value = "/dist/*")
//效果：当浏览器访问{应用名}/dist时，视同访问项目根目录下的/download，点击文件夹可以打开查看内部文件和文件夹，点击文件可以下载
public class DistServlet extends HttpServlet {

	private String BASE_PATH;

	@Override
	public void init() throws ServletException {
		BASE_PATH = getServletContext().getRealPath("download");
		getServletContext().setAttribute("BASE_PATH", BASE_PATH);
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		///tomcat/tomcat-8/v8.5.37/apache-tomcat-8.5.37.zip
		String requestURI = request.getRequestURI();
		//当URL里面存在中文时，例如/dist/恶意.zip，会被进行URL转码，变成%2Fdist%2F%E6%81%B6%E6%84%8F.zip这样，必须进行URL解码
		//ps.以后看到%后面跟两个十六进制数的乱码，类似%2F%E6%81%B6%E6这样的，要知道是URL编码
		//URL编码解码工具网站：https://tool.chinaz.com/tools/urlencode.aspx
		requestURI = URLDecoder.decode(requestURI, "UTF-8");
		String relativePath = requestURI.replace(request.getContextPath() + "/dist", "");
		//当访问的是/dist/的时候，进行上述步骤处理后，会留下来一个/，没必要有
		if (relativePath.equals("/")) {
			relativePath = "";
		}
		//给用户看的路径，消去应用名这一段
		String pathForShow = requestURI.replace(request.getContextPath(), "");
		String filePath = BASE_PATH + relativePath;
		File file = new File(filePath);
		//如果文件不存在
		if (!file.exists()) {
			response.setStatus(404);
			return;
		}
		//如果存在则创建输出流
		ServletOutputStream outputStream = response.getOutputStream();
		if (file.isDirectory()) {
			//如果是目录，则拼接一个html
			//可以先在html文件中写好，再复制过来
			//这是整个页面的模板
			String htmlTemplate = "<!DOCTYPE html>\n" +
					"<html lang=\"en\">\n" +
					"    <head>\n" +
					"        <meta charset=\"UTF-8\">\n" +
					"        <title>文件列表</title>\n" +
					"    </head>\n" +
					"    <body>\n" +
					"        <h2>当前路径：@current_path@</h2>\n" +
					"        @file_links@\n" +
					"    </body>\n" +
					"</html>";
			//这是每个链接的模板
			String aTagTemplate = "<a href=\"@file_href@\">@file_name@</a>";
			//替换给用户看的路径
			String replacePathForShow = htmlTemplate.replace("@current_path@", pathForShow);
			System.out.println(replacePathForShow);
			StringBuilder links = new StringBuilder();
			File[] files = file.listFiles();
			if (files != null && files.length > 0) {
				for (File Content : files) {
					String contentName = Content.getName();
					//替换链接显示的文件名
					String replaceFileName = aTagTemplate.replace("@file_name@", contentName);
					//替换链接指向的地址
					String replaceHref = replaceFileName.replace("@file_href@", requestURI + "/" + contentName);
					System.out.println(replaceHref);
					//把所有链接拼到一起，中间加换行
					links.append(replaceHref).append("<br/>");
				}
				//组装成品页面
				String realHtml = replacePathForShow.replace("@file_links@", links);
				System.out.println(realHtml);
				byte[] bytes = realHtml.getBytes(StandardCharsets.UTF_8);
				outputStream.write(bytes);
				outputStream.close();
				return;
			}
		}
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(filePath));
		String fileName = file.getName();
		fileName = URLEncoder.encode(fileName, "UTF-8");
		//设置响应头，让浏览器知道是下载操作，以及下载的文件名是什么
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		byte[] bytes = new byte[1024];
		int readCount;
		while ((readCount = in.read(bytes)) != -1) {
			outputStream.write(bytes, 0, readCount);
			outputStream.flush();
		}
		outputStream.close();
		in.close();
	}
}
